<#
.SYNOPSIS
    CAD插件打包工具（PowerShell 7优化版）
.DESCRIPTION
    生成自解压安装包，支持指定Debug/Release目录，内置GB2312编码安装脚本
.PARAMETER BuildType
    指定打包目录类型，支持Debug或Release，不区分大小写（默认：Debug）
.EXAMPLE
    .\Package-CAD-Plugin.ps1 -BuildType Release
    使用Release目录打包
.EXAMPLE
    .\Package-CAD-Plugin.ps1 debug
    使用Debug目录打包（参数不区分大小写）
#>

# 配置参数与参数定义
param(
    [Parameter(Mandatory = $false, HelpMessage = "指定打包目录（Debug/Release），不区分大小写")]
    [ValidateSet("Debug", "Release", IgnoreCase = $true)]  # 支持不区分大小写的参数验证
    [string]$BuildType = "Debug"  # 默认值：Debug
)

$projectFileExtensions = @(".csproj", ".vbproj", ".fsproj")

$fallbackVersion = "1.0.0"
# 定义GB2312编码（代码页936）
$gb2312Encoding = [System.Text.Encoding]::GetEncoding(936)








# 初始化错误跟踪变量
$step = "初始化"

try {
    # 步骤1: 检测PowerShell版本
    $step = "检测PowerShell版本"
    Write-Host "`n=== 步骤1: 检测到PowerShell版本: $($PSVersionTable.PSVersion) ==="
    if ($PSVersionTable.PSVersion.Major -lt 7) {
        Write-Error "不支持的PowerShell版本，需要PowerShell 7或更高版本"
        exit 1
    }

    # 步骤2: 输出当前打包类型（统一转为首字母大写显示）
    $formattedBuildType = $BuildType.Substring(0,1).ToUpper() + $BuildType.Substring(1).ToLower()
    Write-Host "`n=== 步骤2: 确认打包配置 ==="
    Write-Host "当前打包目录类型: $formattedBuildType"

    # 步骤3: 定位WinRAR路径
    $step = "定位WinRAR路径"
    Write-Host "`n=== 步骤3: 定位WinRAR路径 ==="
    $winRARPath = if (Test-Path "${env:ProgramFiles}\WinRAR\WinRAR.exe") {
        "${env:ProgramFiles}\WinRAR\WinRAR.exe"
    } elseif (Test-Path "${env:ProgramFiles(x86)}\WinRAR\WinRAR.exe") {
        "${env:ProgramFiles(x86)}\WinRAR\WinRAR.exe"
    } else {
        Write-Error "未找到WinRAR安装路径，请先安装WinRAR"
        exit 1
    }
    Write-Host "找到WinRAR: $winRARPath"

    # 步骤4: 让用户选择项目文件（图形化对话框）
    $step = "选择项目文件"
    Write-Host "`n=== 步骤4: 选择项目文件 ==="
    Add-Type -AssemblyName System.Windows.Forms
    $fileDialog = New-Object System.Windows.Forms.OpenFileDialog
    $fileDialog.Filter = "项目文件 ($($projectFileExtensions -join ','))|$($projectFileExtensions -join ';*')|所有文件 (*.*)|*.*"
    $fileDialog.Title = "选择CAD插件项目文件（当前打包: $formattedBuildType）"
    $fileDialog.InitialDirectory = (Get-Location).Path
    $fileDialog.Multiselect = $false

    $result = $fileDialog.ShowDialog()
    if ($result -ne [System.Windows.Forms.DialogResult]::OK -or [string]::IsNullOrEmpty($fileDialog.FileName)) {
        throw "未选择项目文件，操作取消"
    }
    $projectFile = Get-Item -Path $fileDialog.FileName -ErrorAction Stop
    Write-Host "已选择项目文件: $($projectFile.FullName)"

    # 步骤5: 获取项目信息（名称、路径、版本、cad版本）
    $step = "获取项目信息"
    Write-Host "`n=== 步骤5: 获取项目信息 ==="
    $projectName = $projectFile.BaseName
    $projectDir = $projectFile.Directory.FullName
    # 获取cad的版本,通过匹配项目名称中的ACAD,ZCAD等
    $cadVersion = if ($projectName -match '(ACAD|ZCAD)') { $matches[1] } else { 'ACAD' }
    Write-Host "CAD版本标识: $cadVersion"
    Write-Host "项目名称: $projectName"
    Write-Host "项目路径: $projectDir"

    # 读取版本信息（多来源兼容）
    [xml]$projXml = Get-Content $projectFile.FullName -Raw -ErrorAction Stop
    $versionXPaths = @(
        "//PropertyGroup/Version",
        "//PropertyGroup/AssemblyVersion",
        "//PropertyGroup/FileVersion",
        "//Version",
        "//AssemblyVersion",
        "//FileVersion"
    )
    $version = $null
    foreach ($xpath in $versionXPaths) {
        $versionNode = $projXml.SelectSingleNode($xpath)
        if ($versionNode -and -not [string]::IsNullOrEmpty($versionNode.InnerText.Trim())) {
            $version = $versionNode.InnerText.Trim()
            Write-Host "从节点 '$xpath' 找到版本: $version"
            break
        }
    }
    # 备选：从AssemblyInfo.cs获取
    if (-not $version) {
        Write-Host "尝试从AssemblyInfo.cs获取版本..."
        $assemblyInfoPath = Join-Path $projectDir "Properties\AssemblyInfo.cs"
        if (Test-Path $assemblyInfoPath) {
            $assemblyInfo = Get-Content $assemblyInfoPath -Raw
            if ($assemblyInfo -match '\[assembly: AssemblyVersion\("(.*?)"\)') {
                $version = $matches[1]
                Write-Host "从AssemblyInfo.cs找到版本: $version"
            }
        }
    }
    # 最终 fallback
    if (-not $version -or [string]::IsNullOrEmpty($version)) {
        $version = $fallbackVersion
        Write-Warning "未找到有效版本信息，使用默认版本: $version"
    }
    Write-Host "最终使用版本: $version"

    # 步骤6: 验证目录路径（使用用户指定的BuildType）
    $step = "验证目录路径"
    Write-Host "`n=== 步骤6: 验证目录路径 ==="
    $buildDir = [System.IO.Path]::GetFullPath((Join-Path $projectDir "bin\$formattedBuildType"))
    $outputDir = [System.IO.Path]::GetFullPath((Join-Path $projectDir "bin"))
    $outputExeName = "$projectName-$version-$cadVersion-$formattedBuildType.exe"  # 输出文件名包含打包类型
    $outputExePath = [System.IO.Path]::GetFullPath((Join-Path $outputDir $outputExeName))

    Write-Host "${formattedBuildType}目录: $buildDir"
    Write-Host "输出目录: $outputDir"
    Write-Host "预期输出文件: $outputExeName"

    if (-not (Test-Path -Path $buildDir -PathType Container)) {
        throw "${formattedBuildType}目录不存在: $buildDir`n请先构建项目（dotnet build -c ${formattedBuildType})"
    }
    # 步骤7: 复制外部安装脚本到打包目录
    $step = "复制安装脚本"
    Write-Host "`n=== 步骤7: 复制安装脚本 ==="
    $installScriptName = if ($cadVersion -eq 'ZCAD') { "installzcad.ps1" } else { "installacad.ps1" }
    $sourceInstallScript = Join-Path $PSScriptRoot $installScriptName
    $destInstallScript = Join-Path $buildDir $installScriptName

    if (-not (Test-Path -Path $sourceInstallScript -PathType Leaf)) {
        throw "未找到安装脚本: $sourceInstallScript"
    }

    Copy-Item -Path $sourceInstallScript -Destination $destInstallScript -Force
    Write-Host "已复制安装脚本到打包目录: $destInstallScript"
   

    # 步骤8: 统计文件数量
    $step = "统计文件数量"
    Write-Host "`n=== 步骤8: 统计文件数量 ==="
    $fileCount = (Get-ChildItem -Path $buildDir -File -Recurse).Count
    Write-Host "待压缩文件总数: $fileCount 个"
    if ($fileCount -eq 0) {
        throw "$formattedBuildType目录中没有文件，无法创建安装包`n请先成功构建项目（dotnet build -c $formattedBuildType）"
    }

    # 步骤9: 创建输出目录
    $step = "创建输出目录"
    Write-Host "`n=== 步骤9: 创建输出目录 ==="
    if (-not (Test-Path -Path $outputDir)) {
        Write-Host "创建输出目录: $outputDir"
        $null = New-Item -Path $outputDir -ItemType Directory -Force
    } else {
        Write-Host "输出目录已存在: $outputDir"
    }

    # 步骤10: 创建WinRAR配置文件（GB2312编码）
    $step = "创建WinRAR配置文件"
    Write-Host "`n=== 步骤10: 创建WinRAR配置文件 ==="
    $configFile = [System.IO.Path]::GetTempFileName()
    Write-Host "配置文件路径: $configFile"
    
    # 配置文件内容（标题包含打包类型）
    $configContent = @'
; WinRAR自解压配置
Setup=powershell -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File "{0}" -ProjectName "{1}"
Silent=0
Overwrite=1
Stay=1
Title=安装 {1} v{2} （{3}版）
'@ -f $installScriptName, $projectName, $version, $formattedBuildType

    # 使用GB2312编码写入配置文件
    [System.IO.File]::WriteAllText($configFile, $configContent, $gb2312Encoding)
    Write-Host "已使用GB2312编码写入配置文件"

    # 步骤11: 修改安装脚本，添加带一行提示的确认逻辑（GB2312编码追加）
    $step = "完善安装脚本"
    Write-Host "`n=== 步骤11: 完善安装脚本 ==="
    
    # 添加安装完成确认对话框代码（仅增加一行提示文本）
    $confirmationCode = @"

# 安装完成后显示确认对话框（增加一行提示）
Add-Type -AssemblyName PresentationFramework
[System.Windows.MessageBox]::Show(
    "$projectName v$version 已成功安装完成！`n`n点击确认后，请重启CAD软件以加载新插件。",
    "安装完成",
    [System.Windows.MessageBoxButton]::OK,
    [System.Windows.MessageBoxImage]::Information,
    [System.Windows.MessageBoxResult]::OK,
    [System.Windows.MessageBoxOptions]::DefaultDesktopOnly
)
"@

    # 使用GB2312编码追加内容
    $existingContent = [System.IO.File]::ReadAllText($destInstallScript, $gb2312Encoding)
    $newContent = $existingContent + $confirmationCode
    [System.IO.File]::WriteAllText($destInstallScript, $newContent, $gb2312Encoding)
    Write-Host "已更新安装脚本，确认框将显示额外提示文本"

    # 步骤12: 执行WinRAR命令
    $step = "执行WinRAR命令"
    Write-Host "`n=== 步骤12: 执行WinRAR命令 ==="
    $arguments = @(
        "a",
        "-r",
        "-sfx",
        "-ep1",
        "-m5",
        "-y",
        "-z`"$configFile`"",
        "`"$outputExePath`"",
        "`"$buildDir\*`""
    )

    Write-Host "WinRAR参数: $($arguments -join ' ')"
    $process = Start-Process -FilePath $winRARPath -ArgumentList $arguments -Wait -PassThru -NoNewWindow
    $exitCode = $process.ExitCode

    if ($exitCode -eq 0) {
        Write-Host "`n✅ 自解压文件创建成功: $outputExePath"
        
        # 显示创建成功的确认框
        Add-Type -AssemblyName PresentationFramework
        [System.Windows.MessageBox]::Show(
            "安装包创建成功！`n`n文件路径: $outputExePath`n打包类型: $formattedBuildType",
            "操作完成",
            [System.Windows.MessageBoxButton]::OK,
            [System.Windows.MessageBoxImage]::Information
        )
    } else {
        Write-Error "❌ WinRAR执行失败，错误代码: $exitCode`n参考WinRAR错误代码: 0=成功, 1=警告, 2=错误, 9=压缩文件损坏"
        exit $exitCode
    }
}
catch {
    # 详细错误信息输出
    Write-Error @"
`n===== 执行失败 =====
步骤: $step
错误信息: $($_.Exception.Message)
错误位置: $($_.InvocationInfo.PositionMessage)
堆栈跟踪: $($_.ScriptStackTrace)
"@
    
    # 显示错误提示框
    Add-Type -AssemblyName PresentationFramework
    [System.Windows.MessageBox]::Show(
        "执行失败: $($_.Exception.Message)`n`n步骤: $step`n打包类型: $formattedBuildType",
        "操作失败",
        [System.Windows.MessageBoxButton]::OK,
        [System.Windows.MessageBoxImage]::Error
    )
    
    exit 1
}
finally {
    # 清理临时文件
    if ($configFile -and (Test-Path -Path $configFile)) {
        Remove-Item -Path $configFile -Force -ErrorAction SilentlyContinue
        Write-Host "`n已清理临时配置文件"
    }
}
    